// #include <stdio.h>
// #include <unistd.h>
// #include <signal.h>
// #include <stdlib.h>
// #include <iostream>
// using namespace std;
// void sigcb(int signo)//自定义操作
// {
//   printf("catch a signal : %d\n", signo);
// }
// int main()
// {
//     signal(SIGINT, sigcb);
//     while(1)
//     {
//         raise(SIGINT);
//         sleep(2);
//     }
//     return 0;
// }


////raise函数
// #include <stdio.h>
// #include <unistd.h>
// #include <signal.h>
// #include <stdlib.h>
// #include <iostream>
// using namespace std;
// void handler(int signo)
// {
//   printf("catch a signal : %d\n", signo);
// }

// int main()
// {
//   signal(2, handler);
//   while(1){
//      raise(2);
//      sleep(1);
//   }
//   return 0;
// }


////abort函数
// #include <stdio.h>
// #include <unistd.h>
// #include <signal.h>
// #include <stdlib.h>
// #include <iostream>
// using namespace std;
// int main()
// {
//   while(1){
//      abort();
//   }
//   return 0;
// }


// //sigaction函数
// #include <stdio.h>
// #include <unistd.h>
// #include <signal.h>
// using namespace std;
// void sigcb(int signo)
// {
//   printf("catch a signal: %d\n", signo);
// }

// int main()
// {
//   struct sigaction act, oact;

//   act.sa_flags = 0;// 选项 设置为0
//   sigfillset(&act.sa_mask);
//   act.sa_handler = sigcb;
//   // 对2号信号修改处理动作
//   sigaction(SIGINT, &act, &oact);
//   while (1){
//     raise(SIGINT);
//     sleep(1);
//   }
//   return 0;
// }

////sigprocmask函数
#include <iostream>
#include <cassert>
#include <cstring>
#include <unistd.h>
#include <signal.h>

using namespace std;
       
static void PrintPending(const sigset_t &pending)
{
    cout << "当前进程的pending位图: ";
    for(int signo = 1; signo <= 40; signo++)
    {
        if(sigismember(&pending, signo)) cout << "1";
        else cout << "0";
    }
    cout << "\n";
}

static void handler(int signo)
{
    cout << "对特定信号："<< signo << "执行捕捉动作" << endl;

}
int i=5;

int main()
{
    // 2.0 设置对2号，40号信号的的自定义捕捉
    signal(2, handler);
    signal(40, handler);
    int cnt = 0;
    //1. 屏蔽2号，40号信号
    sigset_t set, oset;
    // 1.1 初始化
    sigemptyset(&set);
    sigemptyset(&oset);
    // 1.2 将2号，40号信号添加到set中
    sigaddset(&set, SIGINT/*2*/);
    sigaddset(&set, SIGRTMIN+6/*40*/);
    // 1.3 将新的信号屏蔽字设置进程
    sigprocmask(SIG_BLOCK, &set, &oset);

    //2. while获取进程的pending信号集合，并01打印

    while(true)
    {
        // 2.1 先获取pending信号集
        sigset_t pending;
        sigemptyset(&pending); // 不是必须的
        int n = sigpending(&pending);
        assert(n == 0);
        (void)n; //保证不会出现编译是的warning

        // 2.2 打印，方便我们查看
        PrintPending(pending);

        // 2.3 休眠一下
        sleep(1);
        while(i)
        {
            raise(2);
            raise(40);
            i--;
        }
        // 2.4 10s之后，恢复对所有信号的block动作
        if(cnt++ == 10)
        {
            cout << "解除对2号,40号信号的屏蔽" << endl; //先打印
            sigprocmask(SIG_SETMASK, &oset, nullptr); 
            exit(1);
        }
    }
}














// //SIGCHILD信号
// #include <stdio.h>
// #include <stdlib.h>
// #include <sys/types.h>
// #include <unistd.h>
// #include <signal.h>
// #include <sys/wait.h>
// #include <pthread.h>
// using namespace std;
// pid_t id;
// void handler(int signo)
// {
// 	// 1. 我有非常多的子进程，在同一个时刻退出了 【只需要循环处理】
// 	// 2. 我有非常多的子进程，在同一个时刻只有一部分退出了 【必须非阻塞式等待，因为操作系统不知道你有多少个子进程要退出
// 	//如果你没退出，在这里就会造成死循环】
// 	//waitpid第一个参数是pid，这里是多个子进程，所以设置-1，意思是会等待任意一个子进程
// 	  printf("捕捉到一个信号: %d, who: %d\n", signo, getpid());
//     sleep(5);

//     // 5个退出，5个没退
//     while (1)
//     {
//         pid_t res = waitpid(-1, NULL, WNOHANG);
//         if (res > 0)
//         {
//             printf("wait success, res: %d, id: %d\n", res, id);
//         }
//         else break; // 如果没有子进程了？
//     }
// }
// void Count(int cnt)
// {
//     while (cnt)
//     {
//         printf("cnt: %2d\r", cnt);
//         fflush(stdout);
//         cnt--;
//         sleep(1);
//     }
//     printf("\n");
// }
// int main()
// {
// 	signal(17,handler);
// 	printf("我是父进程, %d, ppid: %d\n", getpid(), getppid());
// 	pid_t id=fork();
// 	if(id==0)
// 	{
// 		printf("我是子进程, %d, ppid: %d,我要退出啦\n", getpid(), getppid());
// 		sleep(5);
//         exit(1);
// 	}
// 	//保持父进程在运行
// 	while (1)
//     sleep(1);
// 	return 0;
// }

